#include <jni.h>
#include <string.h>
#include <stdio.h>

#include "opensl_demo_.h"


#ifdef __cplusplus


extern "C" {
#endif


#define FILE_PATH "/sdcard/audioJ.pcm"

/**
 * 音频参数配置
 */
#define SAMPLERATE 44100
#define CHANNELs 1
#define PERIOD_TIME 20  //周期20ms
#define FRAME_SIZE SAMPLERATE*PERIOD_TIME/1000
#define BUFFER_SIZE FRAME_SIZE*CHANNELs

static volatile int recording = 0;
static volatile int playing = 0;

static SLuint32 convertSampleRate(int sampleRate){
    switch(sampleRate) {
        case 8000:
            return SL_SAMPLINGRATE_8;
        case 11025:
            return SL_SAMPLINGRATE_11_025;
        case 16000:
            return SL_SAMPLINGRATE_16;
        case 22050:
            return SL_SAMPLINGRATE_22_05;
        case 24000:
            return SL_SAMPLINGRATE_24;
        case 32000:
            return SL_SAMPLINGRATE_32;
        case 44100:
            return SL_SAMPLINGRATE_44_1;
        case 48000:
            return SL_SAMPLINGRATE_48;
        case 64000:
            return SL_SAMPLINGRATE_64;
        case 88200:
            return SL_SAMPLINGRATE_88_2;
        case 96000:
            return SL_SAMPLINGRATE_96;
        case 192000:
            return SL_SAMPLINGRATE_192;
        default:
            return 0;
    }
}


JNIEXPORT void JNICALL
Java_com_jz_opensl_MainActivity_startRecorder(JNIEnv *env, jobject instance) {
    LOG("recording start");
    pthread_mutex_t mutex;
    pthread_cond_t condition;
    OpenSLHelper helper;
    helper.lock.mutex = &mutex;
    helper.lock.condition = &condition;
    openSLInit(&helper);
    recorderInit(&helper, CHANNELs, convertSampleRate(SAMPLERATE));

    FILE *fp = fopen(FILE_PATH, "wb");
    short *buffer = (short*)calloc(BUFFER_SIZE, sizeof(short));
    recording = 1;
    while (recording){
        lockWait(&(helper.lock));
        LOG("recording...");
        (*helper.androidBufferQueueItf)->Enqueue(helper.androidBufferQueueItf, buffer, BUFFER_SIZE*sizeof(short));
        fwrite((unsigned char*)buffer, BUFFER_SIZE*sizeof(short), 1, fp);
    }

    openSLDestroy(&helper);
    free(buffer);
    fclose(fp);
}

JNIEXPORT void JNICALL
Java_com_jz_opensl_MainActivity_stopRecorder(JNIEnv *env, jobject instance) {
    LOG("recording stop");
    recording = 0;

}


JNIEXPORT void JNICALL
Java_com_jz_opensl_MainActivity_stopPlay(JNIEnv *env, jobject instance) {
    playing = 0;
    // TODO

}

JNIEXPORT void JNICALL
Java_com_jz_opensl_MainActivity_startplay(JNIEnv *env, jobject instance) {

    LOG("start play");
    pthread_mutex_t mutex;
    pthread_cond_t condition;
    OpenSLHelper helper;
    helper.lock.mutex = &mutex;
    helper.lock.condition = &condition;
    openSLInit(&helper);
    playerInit(&helper, CHANNELs, convertSampleRate(SAMPLERATE));
    FILE *fp = fopen(FILE_PATH, "rb");
    short *buffer = (short*)calloc(BUFFER_SIZE, sizeof(short));

    playing = 1;
    while (playing){
        lockWait(&(helper.lock));
        if (fread((unsigned char *)buffer, BUFFER_SIZE*sizeof(short), 1, fp) != 1) {
            break;
        }
        LOG("playing...");
        (*helper.androidBufferQueueItf)->Enqueue(helper.androidBufferQueueItf, buffer, BUFFER_SIZE*sizeof(short));
    }

    openSLDestroy(&helper);
    free(buffer);
    fclose(fp);
    playing = 0;
}


JNIEXPORT jint JNICALL
Java_com_jz_opensl_MainActivity_getState(JNIEnv *env, jobject instance) {

    if(recording){
        return 1;
    }

    if(playing){
        return 2;
    }

    return 0;
}

#ifdef __cplusplus
}
#endif